package com.xiao.tripmateai.agent;

import com.xiao.tripmateai.agent.model.AgentState;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * 抽象基础代理类，用于管理代理状态和执行流程。
 * <p>
 * 提供状态转换、内存管理和基于步骤的执行循环的基础功能。
 * 子类必须实现step方法。
 */
@Data
@Slf4j
public abstract class BaseAgent {

    // 事件类型常量 - 用于发布不同阶段的执行状态
    protected static final String EVENT_THINKING = "thinking";
    protected static final String EVENT_ACTION = "action";
    protected static final String EVENT_RESULT = "result";
    protected static final String EVENT_ERROR = "error";
    protected static final String EVENT_FINISHED = "finished";

    // 核心属性
    private String name; // 代理名称

    // 提示词
    private String systemPrompt; // 系统提示词，提供AI模型上下文信息
    private String nextStepPrompt; // 下一步提示词

    // 代理状态 - 跟踪代理当前所处的执行阶段
    private AgentState state = AgentState.IDLE;

    // 执行步骤控制
    private int currentStep = 0; // 当前执行步骤
    private int maxSteps = 10; // 最大执行步骤，防止无限循环

    // LLM 大模型客户端 - 用于与AI模型交互
    private ChatClient chatClient;

    // Memory 记忆 - 维护对话上下文，需要自主管理会话历史
    private List<Message> messageList = new ArrayList<>();

    /**
     * 运行代理 - 同步执行模式
     *
     * @param userPrompt 用户输入的提示词
     * @return 执行结果字符串
     */
    public String run(String userPrompt) {

        // 创建模拟的SSEPublisher - 用于非流式输出场景
        SSEPublisher dummyPublisher = new DummySSEPublisher();

        // 1、基础校验
        if (this.state != AgentState.IDLE) {
            throw new RuntimeException("Cannot run agent from state: " + this.state);
        }
        if (StrUtil.isBlank(userPrompt)) {
            throw new RuntimeException("Cannot run agent with empty user prompt");
        }

        // 2、执行，更改状态
        this.state = AgentState.RUNNING; // 设置代理状态为运行中
        messageList.add(new UserMessage(userPrompt)); // 记录用户输入到消息列表
        List<String> results = new ArrayList<>(); // 保存每一步的执行结果

        try {
            // 执行循环 - 按步骤执行直到完成或达到最大步骤数
            for (int i = 0; i < maxSteps && state != AgentState.FINISHED; i++) {
                int stepNumber = i + 1;
                currentStep = stepNumber;
                log.info("Executing step {}/{}", stepNumber, maxSteps);

                // 执行单步操作，由子类实现具体逻辑
                String stepResult = step(dummyPublisher);
                String result = "Step " + stepNumber + ": " + stepResult;
                results.add(result);
            }

            // 检查是否超出步骤限制
            if (currentStep >= maxSteps) {
                state = AgentState.FINISHED;
                results.add("Terminated: Reached max steps (" + maxSteps + ")");
            }
            return String.join("\n", results); // 返回所有步骤的执行结果
        } catch (Exception e) {
            state = AgentState.ERROR; // 发生异常时设置状态为错误
            log.error("error executing agent", e);
            return "执行错误" + e.getMessage();
        } finally {
            // 3、清理资源
            this.cleanup();
        }
    }

    /**
     * 运行代理（流式输出）- 异步执行模式，通过SSE实现实时输出
     *
     * @param userPrompt 用户输入的提示词
     * @return SseEmitter对象，用于客户端接收流式事件
     */
    public SseEmitter runStream(String userPrompt) {
        SseEmitter sseEmitter = new SseEmitter(300000L); // 创建SSE发射器，设置5分钟超时
        SSEPublisher publisher = new RealSSEPublisher(sseEmitter); // 创建真实的SSE发布器

        // 异步执行代理逻辑
        CompletableFuture.runAsync(() -> {
            try {
                // 1. 基础校验
                if (this.state != AgentState.IDLE) {
                    publisher.publish(EVENT_ERROR, "代理当前状态为 " + this.state + "，无法执行新任务");
                    publisher.complete(); // 发送完成事件
                    return;
                }
                if (StrUtil.isBlank(userPrompt)) {
                    publisher.publish(EVENT_ERROR, "请输入有效的提示词");
                    publisher.complete(); // 发送完成事件
                    return;
                }

                // 2. 初始化状态
                this.state = AgentState.RUNNING; // 设置代理状态为运行中
                messageList.add(new UserMessage(userPrompt)); // 记录用户输入

                // 3. 发送初始化信息
                publisher.publish(EVENT_THINKING, "任务开始");
                publisher.publish(EVENT_THINKING, "最大执行步骤数: " + maxSteps);

                // 4. 执行循环
                for (int i = 0; i < maxSteps && state != AgentState.FINISHED; i++) {
                    int stepNumber = i + 1;
                    currentStep = stepNumber;

                    // 发布当前步骤开始事件
                    publisher.publish(EVENT_ACTION, "步骤 " + stepNumber + "/" + maxSteps);

                    // 执行单步操作
                    String stepResult = step(publisher);

                    // 发布步骤结果事件（统一格式）
                    String displayResult = formatStepResult(stepResult); // 新增格式化方法

                    publisher.publish(EVENT_RESULT,
                            "✅ 步骤 " + stepNumber + " 结果: " + displayResult);

                    // 如果任务已完成，提前退出循环
                    if (state == AgentState.FINISHED) {
                        publisher.publish(EVENT_FINISHED, "任务提前完成");
                        break;
                    }
                }

                // 5. 处理结束状态
                if (state == AgentState.FINISHED) {
                    // 任务正常完成
                    publisher.publish(EVENT_FINISHED, "任务成功完成");
                } else if (currentStep >= maxSteps) {
                    // 达到最大步骤数
                    state = AgentState.FINISHED;
                    publisher.publish(EVENT_FINISHED, "已达到最大步骤数 (" + maxSteps + ")，任务终止");
                } else {
                    // 其他原因结束
                    publisher.publish(EVENT_FINISHED, "任务结束");
                }

                // 6. 发送最终结果
                String finalResult = generateFinalResult();
                publisher.publish(EVENT_FINISHED, finalResult);

            } catch (Exception e) {
                state = AgentState.ERROR; // 发生异常时设置状态为错误
                publisher.publish(EVENT_ERROR, "执行错误: " + e.getMessage());
                log.error("代理执行错误", e);
            } finally {
                // 7. 清理资源并完成SSE连接
                try {
                    // 发送完成事件
                    publisher.publish("complete", "任务完成");

                    // 确保发送最终结果
                    if (state == AgentState.FINISHED) {
                        publisher.publish(EVENT_FINISHED, "任务成功完成");
                    } else if (state == AgentState.ERROR) {
                        publisher.publish(EVENT_ERROR, "任务执行出错");
                    }

                    // 延迟确保所有消息都已发送
                    Thread.sleep(100);
                } catch (Exception e) {
                    log.error("发送完成事件失败", e);
                } finally {
                    this.cleanup();
                    publisher.complete(); // 正确关闭连接
                    log.info("代理任务已完成，状态: {}", state);
                }
            }
        });

        // SSE连接回调处理
        sseEmitter.onTimeout(() -> {
            this.state = AgentState.ERROR; // 连接超时时设置状态为错误
            this.cleanup();
            log.warn("SSE连接超时");

            // 发送超时通知
            try {
                sseEmitter.send(SseEmitter.event()
                        .name(EVENT_ERROR)
                        .data("连接超时，请重试"));
            } catch (IOException ignored) {}

            sseEmitter.complete();
        });

        sseEmitter.onCompletion(() -> {
            // 只有在正常完成时更新状态
            if (this.state == AgentState.RUNNING) {
                this.state = AgentState.FINISHED;
            }
            this.cleanup();
            log.info("SSE连接完成");
        });

        return sseEmitter;
    }


    /**
     * 定义单个步骤的执行逻辑
     * 子类必须实现此方法来定义代理的核心行为
     *
     * @param publisher 用于发布事件的SSEPublisher
     * @return 步骤执行结果
     */
    public abstract String step(SSEPublisher publisher);

    /**
     * 清理资源
     * 子类可以重写此方法来清理特定资源
     */
    protected void cleanup() {
        // 子类可以重写此方法来清理资源
    }

    // SSE事件发布器接口 - 定义发布事件和完成的方法
    public interface SSEPublisher {
        void publish(String eventType, String content);
        void complete();
    }

    // 真实的SSE发布器实现 - 用于流式输出场景
    protected static class RealSSEPublisher implements SSEPublisher {
        private final SseEmitter emitter;

        public RealSSEPublisher(SseEmitter emitter) {
            this.emitter = emitter;
        }

        @Override
        public void publish(String eventType, String content) {
            try {
                // 添加表情符号增强可读性
                String enhancedContent = switch(eventType) {
                    case EVENT_THINKING -> "💭 " + content;
                    case EVENT_ACTION -> "⚡ " + content;
                    case EVENT_RESULT -> "📋 " + content;
                    case EVENT_ERROR -> "❌ " + content;
                    case EVENT_FINISHED -> "🎉 " + content;
                    default -> content;
                };

                emitter.send(SseEmitter.event()
                        .name(eventType)
                        .data(enhancedContent));
            } catch (IOException e) {
                log.error("SSE发送失败", e);
            }
        }

        @Override
        public void complete() {
            try {
                emitter.complete(); // 完成SSE连接
            } catch (Exception e) {
                log.warn("SSE完成时出错", e);
            }
        }
    }

    // 模拟的SSE发布器实现 - 用于非流式场景（同步执行）
    protected static class DummySSEPublisher implements SSEPublisher {
        @Override
        public void publish(String eventType, String content) {
            // 非流式场景不做任何操作，仅记录调试信息
            log.debug("模拟事件: [{}] {}", eventType, content);
        }

        @Override
        public void complete() {
            // 非流式场景不做任何操作
        }
    }

    /**
     * 生成最终结果摘要
     */
    private String generateFinalResult() {
        // 这里可以添加逻辑来生成任务的最终摘要
        // 例如：提取关键信息、总结任务结果等
        return "🚀 任务完成！共执行 " + currentStep + " 步，最后状态: " + state;
    }

    /**
     * 精简长文本，添加省略号
     *
     * @param text 原始文本
     * @param maxLength 最大长度
     * @return 精简后的文本
     */
    private String abbreviate(String text, int maxLength) {
        if (StrUtil.isBlank(text)) {
            return "";
        }

        if (text.length() <= maxLength) {
            return text;
        }

        return text.substring(0, maxLength) + "...";
    }

    // 新增结果格式化方法
    private String formatStepResult(String rawResult) {
        // 简化工具调用响应
        if (rawResult.contains("ToolResponse")) {
            return rawResult
                    .replaceAll("(?s)\"responseData\":\\[.*?\\]", "\"responseData\":[精简数据]")
                    .replaceAll("\\s{2,}", " ")
                    .substring(0, Math.min(rawResult.length(), 300)) + "...";
        }
        // 简化AI思考过程
        if (rawResult.contains("reasoningContent")) {
            return rawResult.substring(0, Math.min(rawResult.length(), 150)) + "...";
        }
        return rawResult;
    }


}